/*
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.novelot.plugin.allinone.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class ShellUtils {
    public static class ShellResult {
        List<String> result = new ArrayList<>();
        List<String> errorResult = new ArrayList<>();
        Exception e;

        public List<String> getResult() {
            return result;
        }

        public ShellResult setResult(List<String> result) {
            this.result = result;
            return this;
        }

        public List<String> getErrorResult() {
            return errorResult;
        }

        public ShellResult setErrorResult(List<String> errorResult) {
            this.errorResult = errorResult;
            return this;
        }

        public Exception getE() {
            return e;
        }

        public ShellResult setE(Exception e) {
            this.e = e;
            return this;
        }
    }

    public interface ShellOutput {

        void outputDebug(String msg);

        void outputError(String msg);
    }

    public static class LogShellOutput implements ShellOutput {
        public void outputDebug(String msg) {
            Logger.i(msg);
        }

        public void outputError(String msg) {
            Logger.w(msg);
        }
    }

    public static ShellOutput ALL = new LogShellOutput();

    public static ShellResult runShells(String... cmds) {
        return runShells(ALL, cmds);
    }

    public static ShellResult runShells(ShellOutput output, String... cmds) {
        ShellResult result = new ShellResult();

        List<String> cmdArray = new ArrayList<>();

        cmdArray.add("/bin/sh");
        cmdArray.add("-c");

        StringBuilder sb = new StringBuilder();
        for (String cmd : cmds) {
            if (sb.length() > 0) {
                sb.append('\n');
            }
            sb.append(cmd);

            output.outputDebug(cmd);
        }
        cmdArray.add(sb.toString());

        try {
            Process process = Runtime.getRuntime().exec(cmdArray.toArray(new String[cmdArray.size()]));
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String line;

            while (process.isAlive()) {
                process.waitFor(200, TimeUnit.MILLISECONDS);
                while ((line = reader.readLine()) != null) {
                    result.getResult().add(line);

                    output.outputDebug(line);
                }

                while ((line = errorReader.readLine()) != null) {
                    result.getErrorResult().add(line);

                    output.outputError(line);
                }
            }
        } catch (Exception e) {
            output.outputError(Logger.getStackTraceString(e));
        }

        return result;
    }
}

